/**
 * File: MatchDetails.java
 * Created by: mhaimel
 * Created on: Jul 5, 2010
 * CVS:  $Id: MatchDetails.java 1.0 Jul 5, 2010 1:25:04 PM mhaimel Exp $
 */
package uk.ac.ebi.curtain.utils.match;

import java.util.Collection;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;

import uk.ac.ebi.curtain.utils.concurrent.CurtainAtomicIntegerArray;
import uk.ac.ebi.curtain.utils.file.FileInfo;
import uk.ac.ebi.curtain.utils.match.sam.AlternativeMatch;
import uk.ac.ebi.velvet.model.Strand;

/**
 * @author mhaimel
 *
 */
public class MatchDetails {
	
	private final FileInfo fileInfo;
	private final String reference;
	private final String readId;
	private final AtomicInteger readLength = new AtomicInteger(0);
	private final AtomicInteger alignLength = new AtomicInteger(0);
	private final AtomicInteger referenceLocation = new AtomicInteger(-1);
	private final AtomicInteger readLocation = new AtomicInteger(0);
	private final CurtainAtomicIntegerArray qualities;
	private final AtomicInteger alignBlocks = new AtomicInteger(0);
	private final AtomicInteger alignBlockNumber = new AtomicInteger(0);
	private final AtomicReference<Strand> readOrientation = new AtomicReference<Strand>();
	private final AtomicReference<Strand> alignOrientation = new AtomicReference<Strand>();
	private final AtomicReference<String> sequence = new AtomicReference<String>();
	
	private final AtomicBoolean repeatMarker = new AtomicBoolean(false);
	private final CopyOnWriteArrayList<AlternativeMatch> alternatives = new CopyOnWriteArrayList<AlternativeMatch>();

	private final AtomicBoolean mapped = new AtomicBoolean(false);
	private final AtomicBoolean paired = new AtomicBoolean(false);
	private final AtomicBoolean properPaired = new AtomicBoolean(false);
	private final AtomicBoolean differentContig = new AtomicBoolean(false);
	private final AtomicBoolean otherMapped = new AtomicBoolean(false);
	
	public MatchDetails(FileInfo fileInfo, String reference, String readId, int[] qualities) {
		super();
		this.fileInfo = fileInfo;
		this.reference = reference;
		this.readId = readId;
		this.qualities = new CurtainAtomicIntegerArray(qualities);
	}

	/**
	 * @return the fileInfo
	 */
	public FileInfo getFileInfo() {
		return fileInfo;
	}

	/**
	 * @return the reference
	 */
	public String getReference() {
		return reference;
	}

	/**
	 * @return the readId
	 */
	public String getReadId() {
		return readId;
	}

	/**
	 * @return the length
	 */
	public int getReadLength() {
		return readLength.get();
	}
	
	public void setReadLength(Integer readLength) {
		this.readLength.set(readLength);
	}
	
	/**
	 * 
	 * @return the alignLength
	 */
	public int getAlignLength() {
		return alignLength.get();
	}
	
	public void setAlignLength(Integer alignLength) {
		this.alignLength.set(alignLength);
	}

	/**
	 * @return the referenceLocation
	 */
	public int getReferenceLocation() {
		return referenceLocation.get();
	}
	
	public void setReferenceLocation(Integer referenceLocation) {
		this.referenceLocation.set(referenceLocation);
	}
	
	/**
	 * @return the readLocation
	 */
	public int getReadLocation() {
		return readLocation.get();
	}
	
	public void setReadLocation(Integer readLocation) {
		this.readLocation.set(readLocation);
	}	
	
	public int getQualitiesLength(){
		return qualities.length();
	}

	/**
	 * @return the qualities
	 */
	public int getQualities(int i) {
		return qualities.get(i);
	}

	/**
	 * @return the readOrientation
	 */
	public Strand getReadOrientation() {
		return readOrientation.get();
	}
	
	public void setReadOrientation(Strand readOrientation) {
		this.readOrientation.set(readOrientation);
	}

	/**
	 * @return the alignOrientation
	 */
	public Strand getAlignOrientation() {
		return alignOrientation.get();
	}
	
	public void setAlignOrientation(Strand alignOrientation) {
		this.alignOrientation.set(alignOrientation);
	}

	/**
	 * @return the mapped
	 */
	public boolean getMapped() {
		return mapped.get();
	}
	
	public void setMapped(boolean mapped) {
		this.mapped.set(mapped);
	}

	/**
	 * @return the paired
	 */
	public boolean getPaired() {
		return paired.get();
	}
	
	public void setPaired(boolean paired) {
		this.paired.set(paired);
	}
	
	/**
	 * @return the properPaired
	 */
	public boolean getProperPaired() {
		return properPaired.get();
	}
	
	public void setProperPaired(boolean paired) {
		this.properPaired.set(paired);
	}

	/**
	 * @return the differentContig
	 */
	public boolean getDifferentContig() {
		return differentContig.get();
	}
	
	public void setDifferentContig(boolean differentContig) {
		this.differentContig.set(differentContig);
	}

	/**
	 * @return the otherMapped
	 */
	public boolean getOtherMapped() {
		return otherMapped.get();
	}
	
	public void setOtherMapped(boolean otherMapped) {
		this.otherMapped.set(otherMapped);
	}
	
	public void setAlignBlocks(Integer alignBlocks) {
		this.alignBlocks.set(alignBlocks);
	}
	
	public int getAlignBlocks() {
		return alignBlocks.get();
	}
	
	public void setAlignBlockNumber(Integer number) {
		this.alignBlockNumber.set(number);
	}
	
	public int getAlignBlockNumber() {
		return alignBlockNumber.get();
	}
	
	public AlternativeMatch[] getAlternatives() {
		return alternatives.toArray(new AlternativeMatch[0]);
	}
	
	public void addAlternatives(AlternativeMatch alternative) {
		this.alternatives.add(alternative);
	}
	
	public boolean getRepeatMarker() {
		return repeatMarker.get();
	}
	
	public void setRepeatMarker(boolean repeatMark) {
		this.repeatMarker.set(repeatMark);
	}
	
	@Override
	public String toString() {
		return ToStringBuilder.reflectionToString(this,ToStringStyle.SHORT_PREFIX_STYLE);
	}

	public void addAlternatives(Collection<AlternativeMatch> altMatches) {
		this.alternatives.addAll(altMatches);
	}
	
	public boolean hasAlternatives(){
		return !this.alternatives.isEmpty();
	}
	
	
	
	public AlternativeMatch getAsAlternativeMatch(){
		AlternativeMatch alt = new AlternativeMatch(this.getReference(),getQualityArray());
		alt.setAlignOrientation(this.getAlignOrientation());
		alt.setReadLocation(this.getReadLength());
		alt.setReadOrientation(this.getReadOrientation());
		alt.setRepeatMarker(this.getRepeatMarker());
		alt.setAlignLength(this.getAlignLength());
		alt.setReferenceLocation(this.getReferenceLocation());
		return alt;
	}

	protected int[] getQualityArray() {
		return this.qualities.toArray();
	}

	public void setReadSequence(String sequence) {
		this.sequence.set(sequence);
	}
	public String getSequence() {
		return sequence.get();
	}
}
